www.gusucode.com > wxApp PHP版微信小程序CMS系统 v1.0PHP源码程序 > wxApp PHP版微信小程序CMS系统 v1.0/wxAppCMS_v1.0.0/wxAppCMS_v1.0.0/app/files/library/UpYun.class.php
<?php /** * @author <[荒野無燈]> * @source [https://github.com/ihacklog/hacklog-remote-attachment-upyun] */ class UpYun { const VERSION = '2.2.0'; const ED_AUTO = 'v0.api.upyun.com'; const ED_TELECOM = 'v1.api.upyun.com'; const ED_CNC = 'v2.api.upyun.com'; const ED_CTT = 'v3.api.upyun.com'; const CONTENT_TYPE = 'Content-Type'; const CONTENT_MD5 = 'Content-MD5'; const CONTENT_SECRET = 'Content-Secret'; // 缩略图 const X_GMKERL_THUMBNAIL = 'x-gmkerl-thumbnail'; const X_GMKERL_TYPE = 'x-gmkerl-type'; const X_GMKERL_VALUE = 'x-gmkerl-value'; const X_GMKERL_QUALITY = 'xgmkerl-quality'; const X_GMKERL_UNSHARP = 'xgmkerl-unsharp'; private $_bucketname; private $_username; private $_password; private $_timeout = 30; private $_file_secret = null; private $_content_md5 = null; protected $endpoint; /** * @var string: UPYUN 请求唯一id, 出现错误时, 可以将该id报告给 UPYUN,进行调试 */ private $x_request_id; /** * 初始化 UpYun 存储接口 * @param $bucketname string 空间名称 * @param $username string 操作员名称 * @param $password string 密码 * * @param null $endpoint * @param int $timeout */ public function __construct($bucketname, $username, $password, $endpoint = NULL, $timeout = 30) { $this->_bucketname = $bucketname; $this->_username = $username; $this->_password = md5($password); $this->_timeout = $timeout; $this->endpoint = is_null($endpoint) ? self::ED_AUTO : $endpoint; } /** * 获取当前SDK版本号 */ public function version() { return self::VERSION; } /** * 创建目录 * @param $path string 路径 * @param $auto_mkdir bool 是否自动创建父级目录,最多10层次 * * @return mixed */ public function makeDir($path, $auto_mkdir = true) { $headers = array('Folder' => 'true'); if ($auto_mkdir) $headers['Mkdir'] = 'true'; return $this->_do_request('PUT', $path, $headers); } /** * 删除目录和文件 * @param string $path 路径 * * @return boolean */ public function delete($path) { return $this->_do_request('DELETE', $path); } /** * 上传文件 * @param string $path 存储路径 * @param mixed $file 需要上传的文件,可以是文件流或者文件内容 * @param boolean $auto_mkdir 自动创建目录 * @param array $opts 可选参数 * @return mixed|null */ public function writeFile($path, $file, $auto_mkdir = true, $opts = NULL) { if (is_null($opts)) $opts = array(); if (!is_null($this->_content_md5)) $opts[self::CONTENT_MD5] = $this->_content_md5; if (!is_null($this->_file_secret)) $opts[self::CONTENT_SECRET] = $this->_file_secret; if ($auto_mkdir === true) $opts['Mkdir'] = 'true'; return $this->_do_request('PUT', $path, $opts, $file); } /** * 下载文件 * @param string $path 文件路径 * @param mixed $file_handle * * @return mixed */ public function readFile($path, $file_handle = NULL) { return $this->_do_request('GET', $path, NULL, NULL, $file_handle); } /** * 获取目录文件列表 * * @param string $path 查询路径 * * @return mixed */ public function getList($path = '/') { $rsp = $this->_do_request('GET', $path); $list = array(); if ($rsp) { $rsp = explode("\n", $rsp); foreach ($rsp as $item) { @list($name, $type, $size, $time) = explode("\t", trim($item)); if (!empty($time)) { $type = ($type == 'N') ? 'file' : 'folder'; } $item = array( 'name' => $name, 'type' => $type, 'size' => intval($size), 'time' => intval($time), ); array_push($list, $item); } } return $list; } /** * 获取文件、目录信息 * * @param string $path 路径 * * @return mixed */ public function getFileInfo($path) { $rsp = $this->_do_request('HEAD', $path); return $rsp; } /** * 获取空间使用情况 * @param string $bucket * @return mixed * @throws UpYunAuthorizationException * @throws UpYunException * @throws UpYunForbiddenException * @throws UpYunNotAcceptableException * @throws UpYunNotFoundException * @throws UpYunServiceUnavailable */ public function getFolderUsage($bucket = '/') { return $this->_do_request('GET', "/{$this->_bucketname}/?usage"); } /** * 获取空间存储使用量,单位 byte */ public function getBucketUsage() { return $this->getFolderUsage('/'); } public function getXRequestId() { return $this->x_request_id; } /** * 设置文件访问密钥 */ public function setFileSecret($str) { $this->_file_secret = $str; } /** * 这是文件 md5 校验值 */ public function setContentMd5($str) { $this->_content_md5 = $str; } /** * 连接签名方法 * @param $method string 请求方式 {GET, POST, PUT, DELETE} * @return string 签名字符串 */ private function sign($method, $uri, $date, $length) { //$uri = urlencode($uri); $sign = "{$method}&{$uri}&{$date}&{$length}&{$this->_password}"; return 'UpYun ' . $this->_username . ':' . md5($sign); } /** * HTTP REQUEST 封装 * @param string $method HTTP REQUEST方法,包括PUT、POST、GET、OPTIONS、DELETE * @param string $path 除Bucketname之外的请求路径,包括get参数 * @param array $headers 请求需要的特殊HTTP HEADERS * @param array $body 需要POST发送的数据 * @param null $file_handle * @return mixed */ protected function _do_request($method, $path, $headers = NULL, $body = NULL, $file_handle = NULL) { $uri = "/{$this->_bucketname}{$path}"; $ch = curl_init("http://{$this->endpoint}{$uri}"); $_headers = array('Expect:'); if (!is_null($headers) && is_array($headers)) { foreach ($headers as $k => $v) { array_push($_headers, "{$k}: {$v}"); } } $length = 0; $date = gmdate('D, d M Y H:i:s \G\M\T'); if (!is_null($body)) { if (is_resource($body)) { fseek($body, 0, SEEK_END); $length = ftell($body); fseek($body, 0); array_push($_headers, "Content-Length: {$length}"); curl_setopt($ch, CURLOPT_INFILE, $body); curl_setopt($ch, CURLOPT_INFILESIZE, $length); } else { $length = @strlen($body); array_push($_headers, "Content-Length: {$length}"); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); } } else { array_push($_headers, "Content-Length: {$length}"); } array_push($_headers, "Authorization: {$this->sign($method, $uri, $date, $length)}"); array_push($_headers, "Date: {$date}"); curl_setopt($ch, CURLOPT_HTTPHEADER, $_headers); curl_setopt($ch, CURLOPT_TIMEOUT, $this->_timeout); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); if ($method == 'PUT' || $method == 'POST') { curl_setopt($ch, CURLOPT_POST, 1); } else { curl_setopt($ch, CURLOPT_POST, 0); } if ($method == 'GET' && is_resource($file_handle)) { curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_FILE, $file_handle); } if ($method == 'HEAD') { curl_setopt($ch, CURLOPT_NOBODY, true); } $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($http_code == 0){ return array( 'code' =>$http_code, 'message' => 'Connection Failed' ); } curl_close($ch); $header_string = ''; $body = ''; if ($method == 'GET' && is_resource($file_handle)) { $header_string = ''; $body = $response; } else { list($header_string, $body) = explode("\r\n\r\n", $response, 2); } $this->setXRequestId($header_string); if ($http_code == 200) { if ($method == 'GET' && is_null($file_handle)) { $message = $body; } else { $message = $this->_getHeadersData($header_string); } } else { $message = $this->_getErrorMessage($header_string); if (is_null($message) && $method == 'GET' && is_resource($file_handle)) { $message = 'File Not Found'; } } return array( 'code' =>$http_code, 'message' => $message ); } /** * 处理HTTP HEADERS中返回的自定义数据 * * @param string $text header字符串 * * @return array */ private function _getHeadersData($text) { $headers = explode("\r\n", $text); $items = array(); foreach ($headers as $header) { $header = trim($header); if (stripos($header, 'x-upyun') !== False) { list($k, $v) = explode(':', $header); $items[trim($k)] = in_array(substr($k, 8, 5), array('width', 'heigh', 'frame')) ? intval($v) : trim($v); } } return $items; } /** * 获取返回的错误信息 * * @param string $header_string * * @return mixed */ private function _getErrorMessage($header_string) { list($status, $stash) = explode("\r\n", $header_string, 2); list($v, $code, $message) = explode(" ", $status, 3); return $message . " X-Request-Id: " . $this->getXRequestId(); } private function setXRequestId($header_string) { preg_match('~^X-Request-Id: ([0-9a-zA-Z]{32})~ism', $header_string, $result); $this->x_request_id = isset($result[1]) ? $result[1] : ''; } } class UpYunException extends Exception { public function __construct($message, $code, Exception $previous = null) { parent::__construct($message, $code); // For PHP 5.2.x } public function __toString() { return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; } } class UpYunAuthorizationException extends UpYunException { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, 401, $previous); } } class UpYunForbiddenException extends UpYunException { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, 403, $previous); } } class UpYunNotFoundException extends UpYunException { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, 404, $previous); } } class UpYunNotAcceptableException extends UpYunException { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, 406, $previous); } } class UpYunServiceUnavailable extends UpYunException { public function __construct($message, $code = 0, Exception $previous = null) { parent::__construct($message, 503, $previous); } }